package edu.ntnu.superrss.controller;

import edu.ntnu.superrss.controller.domain.FormComment;
import edu.ntnu.superrss.models.Category;
import edu.ntnu.superrss.models.SyndEntryImpl;
import edu.ntnu.superrss.models.SyndFeedImpl;
import edu.ntnu.superrss.models.User;
import edu.ntnu.superrss.service.CategoryService;
import edu.ntnu.superrss.service.EntryService;
import edu.ntnu.superrss.service.FeedService;
import edu.ntnu.superrss.service.UserService;
import edu.ntnu.superrss.utils.SyndEntrySort;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

/**
 * EntriesController is a controller class for various actions.
 * It uses annotations and auto-wiring i Spring to implement the neccesarry
 * mappings to map the controller to functions and views.
 *
 *
 * @author Dyre Hult <dyre.hult at gmail.com>
 */
@Controller
@SessionAttributes("user")
public class EntriesController {

    private UserService userService;
    private EntryService entryService;
    private CategoryService categoryService;
    private FeedService feedService;

    @Autowired
    public void setEntryService(EntryService es) {
        this.entryService = es;
    }

    @Autowired
    public void setUserService(UserService us) {
        this.userService = us;
    }

    @Autowired
    public void setFeedService(FeedService feedService) {
        this.feedService = feedService;
    }

    @Autowired
    public void setCategoryService(CategoryService categoryService) {
        this.categoryService = categoryService;
    }
    /**
     * Maps the index.htm POST to the listEntries function. Handles GET-data.
     * <p>
     * This method displays feeds according to the parameter data order, feedId and categoryId
     *
     *
     * @param order     a String indicating the order the etries should be orderet
     * @param feedId    a Long value containing the id of the feed to be shown
     * @param categoryId a Long value containing the id of the category to be shown
     * @param session   the session containing user data
     * @param model     the ModelMap object used to transfer data to the view
     * @return          the String containing the name of the view to return
     */
    @RequestMapping(value = "/index.htm", method = RequestMethod.GET)
    public String listEntries(
        @RequestParam(required = false, value = "order") String order,
        @RequestParam(required = false, value = "feedId") Long feedId,
        @RequestParam(required = false, value = "categoryId") Long categoryId,
        @ModelAttribute("user") User usr,
        ModelMap model,
        HttpSession session
    ) {
        if (((((User) (session.getAttribute("user"))).getUsername()) == null)) {
            model.addAttribute("errors", "Missing user info");
            return "register";
        }

        List<SyndFeedImpl> feeds = new ArrayList<SyndFeedImpl>();
        User user = userService.getUser(usr);

        //if feedId is null, then all entries should be displayed, if feedId is set, then a specific feed should be displayed
        if (categoryId != null) {
            feeds = (ArrayList<SyndFeedImpl>)feedService.getFeedsByCategory(user.getUsername(), categoryId);
            model.addAttribute("allFeeds", false);
        } else if (feedId != null)  {
            feeds.add(feedService.getFeed(feedId));
            model.addAttribute("allFeeds", false);
        } else {
            feeds = new ArrayList<SyndFeedImpl>(user.getFeeds());
            model.addAttribute("allFeeds", true);
        }
        
        List<SyndEntryImpl> entries = new ArrayList();
        for (SyndFeedImpl feed : feeds) {
            entries.addAll(feed.getEntries());
        }

        //changes the feed entries in the object, but doesn't update database. This way all users will see a different list of entries read/unread
        List<SyndEntryImpl> unreadEntries = new ArrayList<SyndEntryImpl>(entries);
        unreadEntries.removeAll(user.getEntriesRead());
        if (order != null && order.equals("random")) {
            Collections.shuffle(unreadEntries);
        } else if (order != null && order.equals("oldest")) {
            Collections.sort(unreadEntries, Collections.reverseOrder(SyndEntrySort.DATE_ORDER));
        } else if (order != null && order.equals("like")) {
            Collections.sort(unreadEntries, SyndEntrySort.THUMB_ORDER);
        } else {
            Collections.sort(unreadEntries, SyndEntrySort.DATE_ORDER);
        }

        List<Category> categories = (ArrayList<Category>)this.categoryService.getCategories(user);

        model.addAttribute("filterCategories", categories);
        model.addAttribute("filterFeeds", feeds);
        model.addAttribute("title", "Feed content");
        model.addAttribute("entries", unreadEntries);

        for (SyndEntryImpl entry: entries) {
            FormComment formComment = new FormComment();
            formComment.setFeedEntryId(entry.getEntryID());
            model.addAttribute("formComment_"+entry.getEntryID(), formComment);
        }

        return "listEntries";
    }
    /**
     * Maps the feedActionHandler.htm to the entryInteracted method
     * <p>
     * This method controls the actions one can use on a feed.
     * The actions is "markRead" and "thumbUp"
     *
     *
     * @param entryId   a Long indication the id of the entry the action is acted upon
     * @param action    a String indicating the action can be either "markRead" and "thumbUp"
     * @param session   the session containing user data
     * @param model     the ModelMap object used to transfer data to the view
     * @return          the String containing the name of the view to return
     */
    @RequestMapping(value = "/feedActionHandler.htm", method = RequestMethod.GET)
    public String entryInteracted(@RequestParam(required = false, value = "feedId") Long feedId,
            @RequestParam(required = true, value = "entryId") Long entryId,
            @RequestParam(required = true, value = "action") String action,
            ModelMap model,
            HttpSession httpSession,
            @RequestParam("all") boolean allFeeds) {
        User user = userService.getUser((User) httpSession.getAttribute("user"));

        if (action.equals("markRead")) {
            entryService.markEntryRead(entryId, user);
        } else if (action.equals("thumbUp")) {
            entryService.thumbUpEntry(entryId, user);
        }
        if (allFeeds) {
            return "redirect:index.htm";
        } else {
            return "redirect:index.htm?feedId=" + feedId;
        }
    }
}
